﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Collections.Concurrent;
using System.Data;
using System.Linq;

namespace Fast.Extensions.DatabaseAccessor.EntityFrameworkCore
{
    /// <summary>
    /// 数据库上下文管理器
    /// </summary>
    [SkipScan]
    public class DbContextManager : IDbContextManager
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly ConcurrentDictionary<Guid, DbContext> _dbContexts = new ConcurrentDictionary<Guid, DbContext>();

        public DbContextManager()
        {

        }

        /// <summary>
        /// 获取所有数据库上下文
        /// </summary>
        /// <returns></returns>
        public ConcurrentDictionary<Guid, DbContext> GetDbContexts()
        {
            return _dbContexts;
        }
        /// <summary>
        /// 将上下文添加到管理器中
        /// </summary>
        /// <param name="dbContext"></param>
        public void AddContext(DbContext dbContext)
        {
            if (!_dbContexts.TryAdd(dbContext.ContextId.InstanceId, dbContext)) return;

            //监听保存失败事件
            dbContext.SaveChangesFailed += (sender, e) =>
            {
                // 当前事务
                dynamic context = sender as DbContext;
                var database = context.Database as DatabaseFacade;
                var currentTransaction = database?.CurrentTransaction;

                // 只有事务不等于空且支持自动回滚
                if (!(currentTransaction != null && context.FailedAutoRollback == true)) return;

                // 获取数据库连接信息
                var connection = database.GetDbConnection();

                // 回滚事务
                currentTransaction.Rollback();

                // 打印事务回滚消息
                App.PrintToMiniProfiler(MiniProfilerCategory.Transaction.GetDescription(), "Rollback", $"[Connection Id: {context.ContextId}] / [Database: {connection.Database}]{($" / [Connection String: {connection.ConnectionString}]")}", isError: true);
            };

        }
        /// <summary>
        /// 关闭数据库上下文连接
        /// </summary>
        public void CloseConnection()
        {
            if (!_dbContexts.Any()) return;

            foreach (var context in _dbContexts)
            {
                var connection = context.Value.Database.GetDbConnection();
                if (connection.State == ConnectionState.Open)
                {
                    connection.Close();
                    App.PrintToMiniProfiler(MiniProfilerCategory.Sql.GetDescription(), $"Close", $"Connection Close()");
                }
            }
        }
    }
}
